/*
 *
 * *******************************************************************
 *   @项目名称: BHex Android
 *   @文件名称: MainDraw.java
 *   @Date: 11/29/18 3:43 PM
 *   @Author: chenjun
 *   @Copyright（C）: 2018 BlueHelix Inc.   All rights reserved.
 *   注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的.
 *  *******************************************************************
 *
 */

package io.bhex.chart.draw;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.util.TypedValue;


import java.util.ArrayList;
import java.util.List;

import io.bhex.chart.BaseKChartView;
import io.bhex.chart.R;
import io.bhex.chart.base.IChartDraw;
import io.bhex.chart.base.IValueFormatter;
import io.bhex.chart.entity.IBOLL;
import io.bhex.chart.entity.ICandle;
import io.bhex.chart.entity.IKLine;
import io.bhex.chart.formatter.ValueFormatter;
import io.bhex.chart.utils.PixelUtils;
import io.bhex.chart.utils.ViewUtil;

/**
 * 主图的实现类
 */

public class MainDraw implements IChartDraw<ICandle> {

    private float mCandleWidth = 0;
    private float mCandleLineWidth = 0;
    private Paint mRedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint mGreenPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint ma5Paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint ma10Paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint ma20Paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint ma60Paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint timePaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    private Paint mUpPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint mMbPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint mDnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    private Paint mSelectorTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint mSelectorBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    private Paint mBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Context mContext;
    private boolean mBrealTime = false;
    private boolean mHide = false;
    private boolean mBoll = false;

    private boolean mCandleSolid=true;

    public MainDraw(BaseKChartView view) {
        Context context=view.getContext();
        mContext=context;
        mRedPaint.setColor(ContextCompat.getColor(context, R.color.chart_red));
        mGreenPaint.setColor(ContextCompat.getColor(context,R.color.chart_green));
        mBackPaint.setColor(Color.parseColor("#cccccc"));
        mBackPaint.setTextSize(PixelUtils.dp2px(mContext,10));
        mBackPaint.setStyle(Paint.Style.FILL);
        mBackPaint.setTextAlign(Paint.Align.CENTER);
        mBackPaint.setAlpha(255);
    }

    public void setLineTime(boolean bRealTime){
        mBrealTime = bRealTime;
    }
    public void setHide(boolean bHide){
        mHide = bHide;
    }
    public void setShowBoll(boolean bShow){
        mBoll = bShow;
    }


    public void DrawHighPricePoint(boolean bLeft, float curX, ICandle point,@NonNull Canvas canvas,BaseKChartView view){
        if (mBrealTime == false && point != null) {
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setTextSize(timePaint.getTextSize());
            paint.setColor(mSelectorBackgroundPaint.getColor());

            float high = view.getMainY(point.getHighPrice());
            if (bLeft == true) {
                canvas.drawText("←" + view.formatValue(point.getHighPrice()), curX, view.fixTextY(high ), paint);
            }
            else {
                String text = view.formatValue(point.getHighPrice()) + "→";
                canvas.drawText(text , curX - paint.measureText(text), view.fixTextY(high), paint);
            }
        }
    }

    public void DrawLowPricePoint(boolean bLeft, float curX, ICandle point,@NonNull Canvas canvas,BaseKChartView view){
        if (mBrealTime == false && point != null) {
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setTextSize(timePaint.getTextSize());
            paint.setColor(mSelectorBackgroundPaint.getColor());
            Paint.FontMetrics metrics = paint.getFontMetrics();
            float textHeight = metrics.descent - metrics.ascent;

            float low = view.getMainY(point.getLowPrice());
            float r = textHeight / 2;
            if (bLeft == true) {
                String text = "←" + view.formatValue(point.getLowPrice());
                canvas.drawText(text, curX, view.fixTextY(low), paint);
            }
            else {
                String text = view.formatValue(point.getLowPrice()) + "→";
                canvas.drawText( text, curX - paint.measureText(text), view.fixTextY(low), paint);
            }

        }
    }
    @Override
    public void drawTranslated(@Nullable ICandle lastPoint, @NonNull ICandle curPoint, float lastX, float curX, @NonNull Canvas canvas, @NonNull BaseKChartView view, int position) {
        if (mBrealTime == false) {
            boolean bOpenBigger = false;
            if(curPoint.getOpenPrice() > lastPoint.getClosePrice())
                bOpenBigger = true;
            drawCandle(view, canvas, curX, curPoint.getHighPrice(), curPoint.getLowPrice(), curPoint.getOpenPrice(), curPoint.getClosePrice(), bOpenBigger);
            //drawCurrentPrice(view,canvas,curX);
            if(mHide == false) {
                if (mBoll == false) {
                    //画ma5
                    if (lastPoint.getMA5Price() != 0) {
                        view.drawMainLine(canvas, ma5Paint, lastX, lastPoint.getMA5Price(), curX, curPoint.getMA5Price());
                    }
                    //画ma10
                    if (lastPoint.getMA10Price() != 0) {
                        view.drawMainLine(canvas, ma10Paint, lastX, lastPoint.getMA10Price(), curX, curPoint.getMA10Price());
                    }
                    //画ma20
                    if (lastPoint.getMA20Price() != 0) {
                        view.drawMainLine(canvas, ma20Paint, lastX, lastPoint.getMA20Price(), curX, curPoint.getMA20Price());
                    }
                }
                else{
                    view.drawMainLine(canvas, mUpPaint, lastX, lastPoint.getUp(), curX, curPoint.getUp());
                    view.drawMainLine(canvas, mMbPaint, lastX, lastPoint.getMb(), curX, curPoint.getMb());
                    view.drawMainLine(canvas, mDnPaint, lastX, lastPoint.getDn(), curX, curPoint.getDn());

                }
            }
        }
        //画realtime
        else {
            view.drawMainFill(canvas, lastX, lastPoint.getClosePrice(), curX, curPoint.getClosePrice());
            if (lastPoint.getMA60Price() != 0) {
                view.drawMainLine(canvas, ma60Paint, lastX, lastPoint.getMA60Price(), curX, curPoint.getMA60Price());
            }
            view.drawMainLine(canvas, timePaint, lastX, lastPoint.getClosePrice(), curX, curPoint.getClosePrice());
        }
    }

    @Override
    public void drawText(@NonNull Canvas canvas, @NonNull BaseKChartView view, int position, float x, float y) {
        ICandle point = (IKLine) view.getItem(position);
        if (mBrealTime == false) {
            if(mHide == false) {
                if(mBoll == false) {
                    String text = "MA5:" + view.formatValue(point.getMA5Price()) + "  ";
                    canvas.drawText(text, x, y, ma5Paint);
                    x += ma5Paint.measureText(text);
                    text = "MA10:" + view.formatValue(point.getMA10Price()) + "  ";
                    canvas.drawText(text, x, y, ma10Paint);
                    x += ma10Paint.measureText(text);
                    text = "MA20:" + view.formatValue(point.getMA20Price()) + "  ";
                    canvas.drawText(text, x, y, ma20Paint);
                }else{
                    String text = "UP:" + view.formatValue(point.getUp()) + "  ";
                    canvas.drawText(text, x, y, mUpPaint);
                    x += mUpPaint.measureText(text);
                    text = "MB:" + view.formatValue(point.getMb()) + "  ";
                    canvas.drawText(text, x, y, mMbPaint);
                    x += mMbPaint.measureText(text);
                    text = "DN:" + view.formatValue(point.getDn()) + "  ";
                    canvas.drawText(text, x, y, mDnPaint);
                }
            }
        }
        else {
            String text = "MA60:" + view.formatValue(point.getMA60Price()) + "  ";
            canvas.drawText(text, x, y, ma60Paint);
        }
        if (view.isLongPress()) {
            drawSelector(view, canvas);
        }
    }

    @Override
    public float getMaxValue(ICandle point) {
        if (mBrealTime == false) {
            if(mHide == false) {
                if(mBoll == false) {

                    return Math.max(point.getHighPrice(), point.getMA20Price());
                }
                else{
                    if (Float.isNaN(point.getUp())) {
                        return Math.max(point.getHighPrice(), point.getMb());
                    }
                    return Math.max(point.getHighPrice(), point.getUp());
                }
            }
            return Math.max(point.getHighPrice(), point.getMA20Price());
        }
        else
            return Math.max(point.getHighPrice(), point.getMA60Price());


    }

    @Override
    public float getMinValue(ICandle point) {
        if (mBrealTime == false) {
            if(mHide == false) {
                if(mBoll == false) {

                    return Math.min(point.getMA20Price(), point.getLowPrice());
                }
                else {
                    if (Float.isNaN(point.getDn())) {
                        return Math.min(point.getMb(), point.getLowPrice());
                    }
                    return Math.min(point.getDn(), point.getLowPrice());
                }
            }
            return Math.min(point.getMA20Price(), point.getLowPrice());
        }
        else
            return Math.min(point.getMA60Price(), point.getLowPrice());
    }

    @Override
    public IValueFormatter getValueFormatter() {
        return new ValueFormatter();
    }

    @Override
    public boolean bRealTime() {
        return mBrealTime;
    }

    public void drawCurrentPrice(BaseKChartView view, Canvas canvas, float x, float currentPrice,Paint paint){
        float yhigh = view.getMainY(view.getCurrentPrice());
        Rect rect = new Rect();
        String text = view.formatValue(currentPrice)+"";
        mBackPaint.getTextBounds(text,0,text.length(),rect);
        float y = view.fixTextY(yhigh);
        //Log.d("BaseKChartView==>:",view.mMainRect.bottom+"==y=="+y+"==t=="+view.mMainRect.top);

        if(y>view.mMainRect.bottom){
            return;
        }
        float width = mBackPaint.measureText("--"+text+"--");
        RectF rectF = new RectF(view.mMainRect.right,y-rect.height()*1.5f,view.mMainRect.right+width,y+rect.height()*0.7f);
        canvas.drawRect(rectF,mBackPaint);
        text = "--"+text;
        if(text.length()>10){
            paint.setTextSize(PixelUtils.dp2px(mContext,9));
        }else{
            paint.setTextSize(PixelUtils.dp2px(mContext,10));
        }
        canvas.drawText(text,x, y , paint);
    }
    /**
     * 画Candle
     * @param canvas
     * @param x      x轴坐标
     * @param highOrigine   最高价
     * @param lowOrigine    最低价
     * @param openOrigine   开盘价
     * @param closeOrigine  收盘价
     */
    private void drawCandle(BaseKChartView view, Canvas canvas, float x, float highOrigine, float lowOrigine, float openOrigine, float closeOrigine, boolean openBigger) {
        float high = view.getMainY(highOrigine);
        float low = view.getMainY(lowOrigine);
        float open = view.getMainY(openOrigine);
        float close = view.getMainY(closeOrigine);
        float r = mCandleWidth / 2;
        float lineR = mCandleLineWidth / 2;
        if (open > close) {
            //实心
            if(mCandleSolid) {
                canvas.drawRect(x - r, close, x + r, open, mRedPaint);
                canvas.drawRect(x - lineR, high, x + lineR, low, mRedPaint);
            }
            else {
                mRedPaint.setStrokeWidth(mCandleLineWidth);
                canvas.drawLine(x, high, x, close, mRedPaint);
                canvas.drawLine(x, open, x, low, mRedPaint);
                canvas.drawLine(x - r + lineR, open, x - r + lineR, close, mRedPaint);
                canvas.drawLine(x + r - lineR, open, x + r - lineR, close, mRedPaint);
                mRedPaint.setStrokeWidth(mCandleLineWidth * view.getScaleX());
                canvas.drawLine(x - r, open, x + r, open, mRedPaint);
                canvas.drawLine(x - r, close, x + r, close, mRedPaint);
            }

        } else if (open < close) {
            canvas.drawRect(x - r, open, x + r, close, mGreenPaint);
            canvas.drawRect(x - lineR, high, x + lineR, low, mGreenPaint);
        } else {
            if(openBigger) {
                canvas.drawRect(x - r, open, x + r, close + 2, mRedPaint);
                canvas.drawRect(x - lineR, high, x + lineR, low, mRedPaint);
            }
            else {
                canvas.drawRect(x - r, open, x + r, close + 2, mGreenPaint);
                canvas.drawRect(x - lineR, high, x + lineR, low, mGreenPaint);
            }
        }
    }

    /**
     * draw选择器
     * @param view
     * @param canvas
     */
    private void drawSelector(BaseKChartView view, Canvas canvas) {
        Paint.FontMetrics metrics = mSelectorTextPaint.getFontMetrics();
        float textHeight = metrics.descent - metrics.ascent;

        int index = view.getSelectedIndex();
        float padding = ViewUtil.Dp2Px(mContext, 3);
        float margin = ViewUtil.Dp2Px(mContext, 4);
        float width = 0;
        float left;
        float top = margin+view.getTopPadding();
        float height = padding * 14 + textHeight * 8;

        ICandle point = (ICandle) view.getItem(index);
        List<String> strings = new ArrayList<>();
        strings.add(view.formatDateTime(view.getAdapter().getDate(index)));
        strings.add((view.mhigh!=null ? view.mhigh : view.getResources().getString(R.string.chart_high))+ ": " + view.formatValue(point.getHighPrice()));
        strings.add((view.mlow!=null ? view.mlow : view.getResources().getString(R.string.chart_low)) + ": " + view.formatValue(point.getLowPrice()));
        strings.add((view.mopen!=null ? view.mopen : view.getResources().getString(R.string.chart_open)) + ": " + view.formatValue(point.getOpenPrice()));
        strings.add((view.mclose!=null ? view.mclose : view.getResources().getString(R.string.chart_close)) + ": " + view.formatValue(point.getClosePrice()));

        float range = point.getClosePrice() - point.getOpenPrice();

        if(point.getOpenPrice() != 0f) {
            String data = new java.text.DecimalFormat("#0.00").format(100f * range/point.getOpenPrice());
            strings.add((view.mchange_rate!=null ? view.mchange_rate : view.getResources().getString(R.string.chart_change_rate)) + ": " + data + "%");
        }
        else
            strings.add((view.mchange_rate!=null ? view.mchange_rate : view.getResources().getString(R.string.chart_change_rate)) + ": " + "--");
        strings.add((view.mchange!=null ? view.mchange : view.getResources().getString(R.string.chart_change)) + ": " + view.formatValue(range));

        strings.add((view.mamount!=null ? view.mamount : view.getResources().getString(R.string.chart_amount)) + ": " + view.formatValue(point.getVolume()));

        for (String s : strings) {
            width = Math.max(width, mSelectorTextPaint.measureText(s));
        }
        width += padding * 2;

        float x = view.translateXtoX(view.getX(index));
        if (x > view.getChartWidth() / 2) {
            left = margin;
        } else {
            left = view.getChartWidth() - width - margin;
        }

        RectF r = new RectF(left, top, left + width, top + height);
        canvas.drawRoundRect(r, padding, padding, mSelectorBackgroundPaint);
        float y = top + padding * 2 + (textHeight - metrics.bottom - metrics.top) / 2;

        for (int i = 0; i < strings.size(); i++) {


            if((i == 5 || i ==6)) {
                 if(range > 0) {
                     Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                     paint.setTextSize(mSelectorTextPaint.getTextSize());
                     paint.setColor(mRedPaint.getColor());
                     canvas.drawText(strings.get(i), left + padding, y, paint);
                 }
                 else if( range < 0) {
                     Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                     paint.setTextSize(mSelectorTextPaint.getTextSize());
                     paint.setColor(mGreenPaint.getColor());
                     canvas.drawText(strings.get(i), left + padding, y, paint);
                 }
                 else
                     canvas.drawText(strings.get(i), left + padding, y, mSelectorTextPaint);
            }
            else
                canvas.drawText(strings.get(i), left + padding, y, mSelectorTextPaint);
            y += textHeight + padding;
        }

    }

    /**
     * 设置蜡烛宽度
     * @param candleWidth
     */
    public void setCandleWidth(float candleWidth) {
        mCandleWidth = candleWidth;
    }

    /**
     * 设置蜡烛线宽度
     * @param candleLineWidth
     */
    public void setCandleLineWidth(float candleLineWidth) {
        mCandleLineWidth = candleLineWidth;
    }

    /**
     * 设置ma5颜色
     * @param color
     */
    public void setMa5Color(int color) {
        this.ma5Paint.setColor(color);
    }

    /**
     * 设置ma10颜色
     * @param color
     */
    public void setMa10Color(int color) {
        this.ma10Paint.setColor(color);
    }

    /**
     * 设置ma20颜色
     * @param color
     */
    public void setMa20Color(int color) {
        this.ma20Paint.setColor(color);
    }

    /**
     * 设置ma60颜色
     * @param color
     */
    public void setMa60Color(int color) {
        this.ma60Paint.setColor(color);
    }

    /**
     * 设置ma60颜色
     * @param color
     */
    public void setTimeColor(int color) {
        this.timePaint.setColor(color);
    }

    /**
     * 设置选择器文字颜色
     * @param color
     */
    public void setSelectorTextColor(int color) {
        mSelectorTextPaint.setColor(color);
    }

    /**
     * 设置选择器文字大小
     * @param textSize
     */
    public void setSelectorTextSize(float textSize){
        mSelectorTextPaint.setTextSize(textSize);
    }

    /**
     * 设置选择器背景
     * @param color
     */
    public void setSelectorBackgroundColor(int color) {
        mSelectorBackgroundPaint.setColor(color);
    }

    /**
     * 设置曲线宽度
     */
    public void setLineWidth(float width)
    {
        timePaint.setStrokeWidth(width);
        ma60Paint.setStrokeWidth(width);
        ma20Paint.setStrokeWidth(width);
        ma10Paint.setStrokeWidth(width);
        ma5Paint.setStrokeWidth(width);
        mUpPaint.setStrokeWidth(width);
        mMbPaint.setStrokeWidth(width);
        mDnPaint.setStrokeWidth(width);
    }

    /**
     * 设置文字大小
     */
    public void setTextSize(float textSize)
    {
        timePaint.setTextSize(textSize);
        ma60Paint.setTextSize(textSize);
        ma20Paint.setTextSize(textSize);
        ma10Paint.setTextSize(textSize);
        ma5Paint.setTextSize(textSize);
        mUpPaint.setTextSize(textSize);
        mMbPaint.setTextSize(textSize);
        mDnPaint.setTextSize(textSize);
    }

    /**
     * 蜡烛是否实心
     */
    public void setCandleSolid(boolean candleSolid) {
        mCandleSolid = candleSolid;
    }

    /**
     * 设置up颜色
     */
    public void setUpColor(int color) {
        mUpPaint.setColor(color);
    }

    /**
     * 设置mb颜色
     * @param color
     */
    public void setMbColor(int color) {
        mMbPaint.setColor(color);
    }

    /**
     * 设置dn颜色
     */
    public void setDnColor(int color) {
        mDnPaint.setColor(color);
    }
}
